#include <iostream>
#include <omp.h>

// 定义结构体T
struct T { 
    T();            // 默认构造函数
    T(int);         // 整数参数构造函数
    ~T();           // 析构函数
    int t;          // 数据成员
};

// 实现结构体T的成员函数
T::T() : t(0) {
    #pragma omp critical
    std::cout << "T默认构造函数被调用，t = " << t << " (线程" << omp_get_thread_num() << ")" << std::endl;
}

T::T(int val) : t(val) {
    #pragma omp critical
    std::cout << "T整数构造函数被调用，t = " << t << " (线程" << omp_get_thread_num() << ")" << std::endl;
}

T::~T() {
    #pragma omp critical
    std::cout << "T析构函数被调用，t = " << t << " (线程" << omp_get_thread_num() << ")" << std::endl;
}

// 函数f()返回T结构体
int f() {
    static int count = 0;
    return ++count;
}

// threadprivate变量定义
static T t1;
#pragma omp threadprivate(t1)

static T t2(23);
#pragma omp threadprivate(t2)

static T t3 = f();
#pragma omp threadprivate(t3)

int main() {
    int num_threads = 4;
    omp_set_num_threads(num_threads);
    
    std::cout << "===== OpenMP threadprivate示例 =====" << std::endl;
    
    // 显示初始值
    std::cout << "\n主线程中的初始值：" << std::endl;
    std::cout << "t1.t = " << t1.t << std::endl;
    std::cout << "t2.t = " << t2.t << std::endl;
    std::cout << "t3.t = " << t3.t << std::endl;
    
    // 修改主线程中的值
    t1.t = 100;
    t2.t = 200;
    t3.t = 300;
    
    std::cout << "\n修改后主线程中的值：" << std::endl;
    std::cout << "t1.t = " << t1.t << std::endl;
    std::cout << "t2.t = " << t2.t << std::endl;
    std::cout << "t3.t = " << t3.t << std::endl;
    
    // 第一个并行区域
    std::cout << "\n===== 第一个并行区域 =====" << std::endl;
    #pragma omp parallel
    {
        int tid = omp_get_thread_num();
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << " 的初始值：" 
                    << "t1.t = " << t1.t 
                    << ", t2.t = " << t2.t 
                    << ", t3.t = " << t3.t << std::endl;
        }
        
        // 修改线程私有变量
        t1.t = 1000 + tid;
        t2.t = 2000 + tid;
        t3.t = 3000 + tid;
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << " 修改后的值：" 
                    << "t1.t = " << t1.t 
                    << ", t2.t = " << t2.t 
                    << ", t3.t = " << t3.t << std::endl;
        }
    }
    
    // 检查主线程的值是否被影响
    std::cout << "\n第一个并行区域后主线程的值：" << std::endl;
    std::cout << "t1.t = " << t1.t << std::endl;
    std::cout << "t2.t = " << t2.t << std::endl;
    std::cout << "t3.t = " << t3.t << std::endl;
    
    // 重置主线程的值
    t1.t = 111;
    t2.t = 222;
    t3.t = 333;
    
    std::cout << "\n重置后主线程的值：" << std::endl;
    std::cout << "t1.t = " << t1.t << std::endl;
    std::cout << "t2.t = " << t2.t << std::endl;
    std::cout << "t3.t = " << t3.t << std::endl;
    
    // 第二个并行区域
    std::cout << "\n===== 第二个并行区域 =====" << std::endl;
    #pragma omp parallel
    {
        int tid = omp_get_thread_num();
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << " 的值：" 
                    << "t1.t = " << t1.t 
                    << ", t2.t = " << t2.t 
                    << ", t3.t = " << t3.t << std::endl;
        }
    }
    
    // 最终检查
    std::cout << "\n最终主线程的值：" << std::endl;
    std::cout << "t1.t = " << t1.t << std::endl;
    std::cout << "t2.t = " << t2.t << std::endl;
    std::cout << "t3.t = " << t3.t << std::endl;
    
    return 0;
}